package cn.bonoon.services.plugins;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import javax.persistence.TypedQuery;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.bonoon.core.IModuleSelected;
import cn.bonoon.core.plugins.AnnouncementService;
import cn.bonoon.entities.interacting.AnnouncementEntity;
import cn.bonoon.entities.interacting.AnnouncementReleaseEntity;
import cn.bonoon.kernel.AccessAuthorityResolver;
import cn.bonoon.kernel.events.OperateEvent;
import cn.bonoon.kernel.support.IOperator;
import cn.bonoon.kernel.support.models.Item;
import cn.bonoon.kernel.support.services.AbstractService;
import cn.bonoon.kernel.util.StringHelper;

@Service
@Transactional(readOnly = true)
public class AnnouncementServiceImpl extends AbstractService<AnnouncementEntity> implements AnnouncementService {
//
//	static final String ql = "select new " + AnnouncementInfo.class.getName()
//			+ "(x.createAt, x.content) from AnnouncementEntity x order by createAt desc";

//	@Override
//	public List<AnnouncementInfo> read(int page, int size) {
//		TypedQuery<AnnouncementInfo> query = __query(AnnouncementInfo.class, ql);
//		int skip = page * size;
//		return query.setFirstResult(skip).setMaxResults(size).getResultList();
//	}
//
//	@Override
//	public List<AnnouncementInfo> read(IOperator opt, int len) {
//		// TODO Auto-generated method stub
//		return Collections.emptyList();
//	}
//
//	@Override
//	public List<AnnouncementInfo> read(String key, IOperator opt, int len) {
//		// TODO Auto-generated method stub
//		return Collections.emptyList();
//	}

//	@Override
//	public List<AnnouncementEntity> byKey(String key) {
//		String ql = "from AnnouncementEntity x where x.key=? order by x.createAt desc";
//		TypedQuery<AnnouncementEntity> tqSelect = __query(AnnouncementEntity.class, ql, key);
//		tqSelect.setMaxResults(5);
//		return tqSelect.getResultList();
////		String ql = "from AnnouncementEntity x where x.key=? order by x.createAt desc";
////		return __list(AnnouncementEntity.class, ql, key);
//	}

	private final String platformSqlNewest = "select x " +
			"from AnnouncementEntity x " +
			"where x.disable=false and x.deleted=false and x.platform=true " +
			"and (x.ownerId=0 or x.ownerId=?) " + 
			"order by x.createAt desc";
	
	private final String systemSqlNewest = "select x.announcement " +
			"from AnnouncementReleaseEntity x " +
			"where x.disable=false and x.key=? " +
			"and x.announcement.deleted=false and x.announcement.disable=false " +
			"and (x.announcement.ownerId=0 or x.announcement.ownerId=?) " + 
			"order by x.announcement.createAt desc";
	
	@Override
	public List<AnnouncementEntity> newests(IOperator user, String key, int limit) {
		return __top(limit, newests(user, key));
	}
	
	private TypedQuery<AnnouncementEntity> newests(IOperator user, String key){
		if(StringHelper.isEmpty(key)){
			//这个是发布到平台的公告，只要登录，都可以看到的
			return __query(AnnouncementEntity.class, platformSqlNewest, user.getOwnerId());
		}
		return __query(AnnouncementEntity.class, systemSqlNewest, key, user.getOwnerId());
	}

	private final String systemSqlTopest = "select x.announcement " +
			"from AnnouncementReleaseEntity x " +
			"where x.announcement.deleted=false and x.announcement.disable=false and x.disable=false " +
			"and x.key=? and x.announcement.topest=true and (x.announcement.topTo is null or x.announcement.topTo>?) " +
			"and (x.announcement.ownerId=0 or x.announcement.ownerId=?) " + 
			"order by x.announcement.createAt desc";

	private final String systemSqlNotop = "select x.announcement " +
			"from AnnouncementReleaseEntity x " +
			"where x.announcement.deleted=false and x.announcement.disable=false and x.disable=false " +
			"and x.key=? and x.announcement.topest=false " +
			"and (x.announcement.ownerId=0 or x.announcement.ownerId=?) " + 
			"order by x.announcement.createAt desc";

	private final String platformSqlTopest = "select x " +
			"from AnnouncementEntity x " +
			"where x.disable=false and x.deleted=false and x.platform=true " +
			"and x.topest=true and (x.topTo is null or x.topTo>?) " +
			"and (x.ownerId=0 or x.ownerId=?) " + 
			"order by x.createAt desc";

	private final String platformSqlNotop = "select x " +
			"from AnnouncementEntity x " +
			"where x.disable=false and x.deleted=false and x.platform=true " +
			"and x.topest=false " +
			"and (x.ownerId=0 or x.ownerId=?) " + 
			"order by x.createAt desc";
	
	@Override
	public List<AnnouncementEntity> moduleAnnouncements(IOperator user, String key, int page) {
		List<AnnouncementEntity> items = null;
		TypedQuery<AnnouncementEntity> tqSelect;
		if(StringHelper.isEmpty(key)){
			if(page == 0){
				items = __list(AnnouncementEntity.class, platformSqlTopest, new Date(), user.getOwnerId());
			}
			
			tqSelect = __query(AnnouncementEntity.class, platformSqlNotop, user.getOwnerId());
		}else{
			if(page == 0){
				//需要加上top
				items = __list(AnnouncementEntity.class, systemSqlTopest, key, new Date(), user.getOwnerId());
			}
			
			tqSelect = __query(AnnouncementEntity.class, systemSqlNotop, key, user.getOwnerId());
		}
		tqSelect.setFirstResult(page * DEFAULT_PAGE_SIZE);
		tqSelect.setMaxResults(DEFAULT_PAGE_SIZE);
		
		if(null != items && !items.isEmpty()){
			items = new ArrayList<>(items);
			items.addAll(tqSelect.getResultList());
		}else{
			items = tqSelect.getResultList();
		}
		
		return items;
	}
	
	@Override
	@Transactional
	public void changeReleaseStatus(IOperator user, Long id) {
		AnnouncementEntity entity = entityManager.find(AnnouncementEntity.class, id);
		entity.setDisable(!entity.isDisable());
		entityManager.merge(entity);
	}
	
	@Override
	public List<Item> releasePlaform(IOperator user, Long id) {
		List<String> selecteds;
		if(null != id && id > 0){
			selecteds = __list(String.class, "select x.key from AnnouncementReleaseEntity x where x.disable=false and x.announcement.id=?", id);
		}else{
			selecteds = Collections.emptyList();
		}
		return AccessAuthorityResolver.valueOf(applicationContext, user).moduleItems(selecteds);
//		List<Item> items = new ArrayList<Item>();
//		if (user.isSuper()) {
//			//items.add(new Item(moduleManager.getId(), moduleManager.getName()));
//			for (IModuleInfo module : moduleManager.modules()) {
//				addTo(items, module, selecteds);
////				items.add(new Item(module.getId(), module.getName()));
//			}
//		} else {
//			for (String key : __list(String.class, "select distinct x.role.moduleKey from RoleAccountEntity x where x.account.id=?", user.getId())) {
//				IModuleInfo module = moduleManager.module(key);
//				if (null != module) {
//					addTo(items, module, selecteds);
////					items.add(new Item(module.getId(), module.getName()));
//				}
//			}
//		}
//
//		return items;
	}
	
//	private void addTo(List<Item> items, IModuleInfo module, List<String> selecteds){
//		Item item = new Item(module.getId(), module.getName());
//		item.setSelected(selecteds.contains(module.getId()));
//		items.add(item);
//	}
	
	@Override
	protected AnnouncementEntity __save(OperateEvent event, AnnouncementEntity entity) throws Exception {
		AnnouncementEntity saved = super.__save(event, entity);
		
		for(String key : nonullKeys(event)){
			newRelease(saved, key);
		}
		
		return saved;
	}

	private void newRelease(AnnouncementEntity saved, String key) {
		AnnouncementReleaseEntity release = new AnnouncementReleaseEntity();
		release.setAnnouncement(saved);
		release.setDisable(saved.isDisable());
		release.setKey(key);
		entityManager.persist(release);
	}
	
	@Override
	protected AnnouncementEntity __update(OperateEvent event, AnnouncementEntity entity) throws Exception {
		List<AnnouncementReleaseEntity> selecteds = new ArrayList<>(__list(AnnouncementReleaseEntity.class, "select x from AnnouncementReleaseEntity x where x.announcement.id=?", entity.getId()));
		NEXT : for(String key : nonullKeys(event)){
			for(AnnouncementReleaseEntity ar : selecteds){
				if(key.equals(ar.getKey())){
					selecteds.remove(ar);
					ar.setDisable(false);
					entityManager.merge(ar);
					continue NEXT;
				}
			}
			
			newRelease(entity, key);
		}
		for(AnnouncementReleaseEntity ar : selecteds){
			ar.setDisable(true);
			entityManager.merge(ar);
		}
		return super.__update(event, entity);
	}
	
	private String[] nonullKeys(OperateEvent event){
		IModuleSelected pe = (IModuleSelected) event.getSource();
		if(pe.getKeys() == null) return new String[0];
		return pe.getKeys();
	}

//	@Override
//	public List<AnnouncementEntity> outside_annoucement() {
//		String ql = "from AnnouncementEntity x where x.type=0 order by x.createAt desc";
//		return __list(AnnouncementEntity.class, ql);
//	}
//
//	@Override
//	public List<AnnouncementEntity> inside_annoucement() {
//		String ql = "from AnnouncementEntity x where x.type=1 order by x.createAt desc";
//		return __list(AnnouncementEntity.class, ql);
//	}
//
//	@Override
//	public List<AnnouncementEntity> inside_annoucement(Long page) {
//		String ql = "from AnnouncementEntity x where x.type=1 order by x.createAt desc";
//		TypedQuery<AnnouncementEntity> tqSelect = __query(AnnouncementEntity.class, ql);
//		tqSelect.setFirstResult((int) ((page - 1) * 5));
//		tqSelect.setMaxResults(5);
//		return tqSelect.getResultList();
//	}
//
//	@Override
//	public List<AnnouncementEntity> outside_annoucement(Long page) {
//		// TODO Auto-generated method stub
//		return null;
//	}

}
